#ifndef CIPODDEVICE_H_
#define CIPODDEVICE_H_

#include <string>
#include <semaphore.h>
#include "CIpodProxy.h"
#include "CIpodProtocol.h"
#include "CIpodNative.h"

#ifdef __cplusplus
extern "C"{
#endif

class IPODProtInitState {
public:
    enum { UNINIT, INITING, SUCCEED, FAILED };
};

class IpodPacket {
public:
    IpodPacket();
    IpodPacket(const IpodPacket &packet);
    ~IpodPacket();

    bool    exit;
    uint16  len;
    uint8   data[IPOD_PACKET_MAX_LENGTH];
    bool    native;
    uint16  total;
    bool    ignore;

    void clear();
};

class CIpodDevice : public CIpodProxy {
public:
    CIpodDevice(const char *path = NULL);
    ~CIpodDevice();

    ipod_t getHandle();
    int getConnMode();
    std::string getPath();
    int send(const uint8 *data, uint16 len, bool native = false);
    bool isDeviceExist();
    bool isExiting();

    int create();
    int connectIap2();
    int destroy();
    int notifyBtStatus(bool connected);
    int notifyUSBAudioStatus(bool enabled);
    int sendMediaCommand(int command);
    int sendMediaCommandDown(int command);
    int sendMediaCommandUp(int command);
    int sendMediaCommandLibraryInfo(void *mediaInfo);
    int sendStartLocationInformation(int start);
    int sendStartDeviceTimeUpdate();
    int sendCallStateUpdateInfo(void *callStateInfo);
    int setPlayingTrackPosition(uint32 position);
    int getShuffleMode(int *mode);
    int getRepeatMode(int *mode);
    int getPlayingTrackDuration(int * duration);
    int getPlayingTrackTitle(std::string &title);
    int getPlayingTrackAlbum(std::string &album);
    int getPlayingTrackArtist(std::string &artist);
    int getPlayingTrackAlbumArtwork();
    int getPlayStatus(IPODPlayStatus *status);
    int getPlayingTrackInfo(int32 *index, uint32 *count);
    int getPlayingChapterInfo(int32 *index, uint32 *count);
    int isListLevelSupported(bool *supported);
    int resetMusicList(uint32 *num);
    int selectMusicList(int32 index, int32 level, uint32 *num);
    int selectMusicPlayingList(int32 index);
    int getMusicList(uint32 startIndex, uint32 readCount, IPODMusicList *musicList);
    int getMusicList_c(uint32 startIndex, uint32 readCount, C_IPODMusicList *musicList);
    int getMusicPlayingList(uint32 startIndex, uint32 readCount, C_IPODMusicList *musicList);
    int launchApp(const char *appBundleID);
    int sendEAData(const uint8 *data, uint16 len);
    int getEANativeState();
    int setLocationInformation(const char *sentence);
    int iap2CarPlayStartSession(int type);
    int iap2OOBBTPairingCompletionInformation(int resultCode );
    int iap2BluetoothPairingAccessoryInformation(const char * inPairingDataP192,const char * inPairingDataP256);
    int iap2BluetoothPairingStatus( int success, const char * cancelReason);

    int ipod_BT_spp_data_pro(int cDataLen, const char * pData);
    int sendWiFiData( int length, const char * ptr );

    static void ipodRegistBtSppSendData(BtSendData n_bt_spp_send_data);
    static void setWiFiDataCallback( WiFiDataCallback callback );
    static BtSendData bt_send_data;
    static WiFiDataCallback wifiDataCallback;
private:
    ipod_t                  m_Handle;
    std::string             m_Path;
    int                     m_connMode;
    int                     m_hidOnce;
    bool                    m_DeviceExist;
    pthread_t               m_ProcTid;
    pthread_t *             m_ProcTidPtr;
    pthread_t               m_RecvTid;
    pthread_t *             m_RecvTidPtr;
    pthread_t               m_NativeTid;
    std::list<IpodPacket *> m_Packets;
    sem_t                   m_PacketSem;
    sem_t                   m_ProtocolSem;
    int                     m_ProtInitState;
    bool                    m_Iap2Support;
    pthread_mutex_t         m_SendMutex;
    pthread_mutex_t         m_PacketMutex;
    CIpodProtocol           *m_Protocol;
    bool                    m_Exiting;

    int openDevice();
    bool isIpodDevice(int handle);
    int checkIap2Support();
    int packetProc(const uint8 *data, uint16 len, bool native);
    void packetAdd(IpodPacket *packet);
    void debugHexBuf(const char *tag, const uint8 *data, uint16 len);
    std::string debugHexBufString(const uint8 *data, uint16 len);
    void debugHexBuf1(const char *tag, const char *data , uint16 len);

    static void *procThread(void *arg);
    static void *recvThread(void *arg);
    static void *nativeThread(void *arg);
};
#ifdef __cplusplus
}
#endif
#endif /* CIPODDEVICE_H_ */
